module csrWriteBuffer(
  input  valid,
  input  illegalInstruction,
  input  [31:0]        inst,
  input  [`OP_W-1:0]   op,
  input  [`XLEN-1:0]   op1,
  input  [`XLEN-1:0]   op2,
  output [`XLEN-1:0]   out,
  output [`EXCEPT:0]   exception,
  // 异步读CSR寄存器
  output [11:0]       rd_csr_addr,
  input  [`XLEN-1:0]  rd_csr_data,
  // 同步写CSR寄存器
  output              wr_csr_en  ,
  output [11:0]       wr_csr_addr,
  output [`XLEN-1:0]  wr_csr_data
);
wire [11:0] csrAddr;
wire [`XLEN-1:0]imm;
wire wen;
wire [`XLEN-1:0] wr_data_RI ;
wire [`XLEN-1:0] wr_data    ;

assign csrAddr    = inst[31:20];
assign imm        = ((op == `CSR_S) || (op == `CSR_C)) ? {59'd0,inst[19:15]} : 
                                                         {rd_csr_data[`XLEN-1:5],inst[19:15]};
assign wr_data_RI = inst[14] ? imm : op1;
assign wr_data    = (op == `CSR_W) ? wr_data_RI                : 
                    (op == `CSR_S) ? rd_csr_data | wr_data_RI  :
                    (op == `CSR_C) ? rd_csr_data & ~wr_data_RI : `ZERO;
assign wen        = ((op == `CSR_W) || (op == `CSR_S) || (op == `CSR_C)) && valid; 

assign rd_csr_addr = csrAddr;
assign wr_csr_addr = csrAddr;
assign wr_csr_data = wr_data;
assign out         = rd_csr_data; 
assign wr_csr_en   = wen ;
// assign exception           = 'd0;
assign exception[`ecall]   =  valid && (op == `CSR_P) && !csrAddr[0] && !csrAddr[1]; 
assign exception[`ebreak]  =  valid && (op == `CSR_P) &&  csrAddr[0] && !csrAddr[1];
assign exception[`mret]    =  valid && (op == `CSR_P) && !csrAddr[0] &&  csrAddr[1] && (inst[29:28] == `PRV_M); 
assign exception[`ilginst] =  valid && illegalInstruction;
assign exception[`sret   ] =  valid && (op == `CSR_P) && !csrAddr[0] &&  csrAddr[1] && (inst[29:28] == `PRV_S);
assign exception[`uret   ] =  valid && (op == `CSR_P) && !csrAddr[0] &&  csrAddr[1] && (inst[29:28] == `PRV_U);
assign exception[`clint  ] = 'd0;
assign exception[`fencei ] = 'd0;
assign exception[`EXCEPT:`fencei+1] = 'd0;
endmodule     